package com.drinks.yiniang.io.api;

import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.drinks.yiniang.common.help.LogoutHelp;
import com.hansen.library.Constants;
import com.hansen.library.entity.BaseJson;
import com.drinks.yiniang.io.http.OkHttpIO;
import com.drinks.yiniang.io.http.ProgressRequestBody;
import com.hansen.library.io.tuple.Tuple2;
import com.hansen.library.listener.APIRequestCallback;
import com.hansen.library.listener.BitmapCallback;
import com.hansen.library.listener.Callback;
import com.hansen.library.listener.OnDownloadListener;
import com.hansen.library.utils.LogUtils;
import com.hansen.library.utils.MD5Util;
import com.hansen.library.utils.StringUtils;
import com.hansen.library.utils.TimeUtil;

import java.io.File;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;

/**
 * Created by han on 2017/5/19 0019.
 */
public class MainApiIO {

    volatile static MainApiIO instance;

    public MainApiIO() {

    }

    static public MainApiIO getInstance() {
        if (instance == null) {
            synchronized (MainApiIO.class) {
                if (instance == null) {
                    instance = new MainApiIO();
                }
            }
        }

        return instance;
    }

    /**
     * 异步get接口
     *
     * @param url        短地址
     * @param paramsMaps 请求参数
     * @param callback   回调
     */
    public void getRequest(@NonNull String url, Map<String, String> paramsMaps, @Nullable final APIRequestCallback<String, Tuple2<Integer, String>> callback) {
        FormBody.Builder builder = new FormBody.Builder();

        SortedMap<String, String> signParams = new TreeMap<String, String>();

        StringBuilder params = new StringBuilder(url);

        params.append("?");

        if (paramsMaps != null && paramsMaps.size() > 0) {

            String mValue;

            //遍历集合, map集合遍历方式
            for (String key : paramsMaps.keySet()) {
                mValue = paramsMaps.get(key);

                if (mValue != null) {
                    params.append(key);
                    params.append("=");
                    params.append(mValue);
                    params.append("&");

                    signParams.put(key, mValue);
                }
            }
        }

        String time = TimeUtil.getCurrentTimeMillis();

        builder.add("time", time).add("sign", MD5Util.sha1AndMd5(StringUtils.createKeyValueSign(signParams) + Constants.KeySignSecret + time));

        OkHttpIO.getInstance().get(params.substring(0, params.length() - 2), builder.build(), new Callback<Tuple2<Integer, String>, Exception>() {
            @Override
            public void onSuccess(Tuple2<Integer, String> res) {
                if (callback != null) {
                    callback.onComplete();

                    try {
                        if (res._1 == 200) {
                            JSONObject jsonObject = JSON.parseObject(res._2);

                            int code = jsonObject.getInteger("code");

                            if (code == 200) {
                                callback.onSuccess(res._2);
                            } else {
                                callback.onError(new Tuple2(code, jsonObject.get("message")));
                            }
                        } else {
                            callback.onError(new Tuple2(res._1, String.format("HTTP CODE : %d", res._1)));
                        }
                    } catch (Exception e) {
                        LogUtils.e("数据解析异常: " + e.getMessage());
                    }
                }
            }

            @Override
            public void onError(Exception error) {
                if (callback != null) {
                    callback.onComplete();

                    if (error instanceof UnknownHostException) {
                        callback.onError(new Tuple2<>(BaseApiIO.RESULT_UNKNOW_HOST_CODE, BaseApiIO.RESULT_UNKNOW_HOST_CODE_MSG));
                    } else if (error instanceof SocketTimeoutException) {
                        callback.onError(new Tuple2<>(BaseApiIO.RESULT_SOCKET_TIMEOUT_CODE, BaseApiIO.RESULT_SOCKET_TIMEOUT_MSG));
                    }

                    LogUtils.e("数据请求异常: " + error.getMessage());
                }
            }
        });
    }

    /**
     * 异步POST接口
     *
     * @param url        短地址
     * @param paramsMaps 请求参数
     * @param callback   回调
     */
    public void postRequest(@NonNull String url, Map<String, String> paramsMaps, @Nullable final APIRequestCallback<String, Tuple2<Integer, String>> callback) {
        FormBody.Builder builder = new FormBody.Builder();

        SortedMap<String, String> signParams = new TreeMap<String, String>();

        if (paramsMaps != null && paramsMaps.size() > 0) {

            String mValue;

            //遍历集合, map集合遍历方式
            for (String key : paramsMaps.keySet()) {
                mValue = paramsMaps.get(key);

                if (mValue != null) {
                    builder.add(key, mValue.trim());
                    signParams.put(key, mValue.trim());
                }
            }

            if (Constants.isDebug) {
                StringBuilder params = new StringBuilder();

                //遍历集合, map集合遍历方式
                for (String key : paramsMaps.keySet()) {
                    params.append(key);
                    params.append("=");
                    params.append(paramsMaps.get(key));
                    params.append("; ");
                }

                LogUtils.d("--->params: " + params);
            }
        }

        String time = TimeUtil.getCurrentTimeMillis();

        builder.add("time", time).add("sign", MD5Util.sha1AndMd5(StringUtils.createKeyValueSign(signParams) + Constants.KeySignSecret + time));

        OkHttpIO.getInstance().post(url, builder.build(), new Callback<Tuple2<Integer, String>, Exception>() {
            @Override
            public void onSuccess(Tuple2<Integer, String> res) {
                if (callback != null) {
                    callback.onComplete();

                    try {
                        if (res._1 == 200) {
                            JSONObject jsonObject = JSON.parseObject(res._2);

                            int code = jsonObject.getInteger("code");

                            if (code == 200) {
                                callback.onSuccess(res._2);
                            } else {
                                callback.onError(new Tuple2(code, jsonObject.get("message")));

                                if (code == -1) {//Token无效,需要重新登录
                                    OkHttpIO.getInstance().cancelAll();
                                    LogoutHelp.doLogout(true);
                                }
                            }
                        } else {
                            callback.onError(new Tuple2(res._1, String.format("HTTP CODE : %d", res._1)));
                        }
                    } catch (Exception e) {
                        LogUtils.e("数据解析异常: " + e.getMessage());
                    }
                }
            }

            @Override
            public void onError(Exception error) {
                if (callback != null) {
                    callback.onComplete();

                    if (error instanceof UnknownHostException) {
                        callback.onError(new Tuple2<>(BaseApiIO.RESULT_UNKNOW_HOST_CODE, BaseApiIO.RESULT_UNKNOW_HOST_CODE_MSG));
                    } else if (error instanceof SocketTimeoutException) {
                        callback.onError(new Tuple2<>(BaseApiIO.RESULT_SOCKET_TIMEOUT_CODE, BaseApiIO.RESULT_SOCKET_TIMEOUT_MSG));
                    }

                    LogUtils.e("数据请求异常: " + error.getMessage());
                }
            }
        });
    }

    /**
     * 异步POST接口 --- 用于上传图片接口
     *
     * @param url              短地址
     * @param paramsMaps       请求参数
     * @param file             文件
     * @param progressListener 进度
     * @param id               文件标识
     * @param callback         回调
     */

    public void uploadImage(@NonNull String url, Map<String, String> paramsMaps, File file, int id, ProgressRequestBody.ProgressListener progressListener, @Nullable final APIRequestCallback<String, Tuple2<Integer, String>> callback) {
        //fileRequestBody 请求body
        ProgressRequestBody fileRequestBody = new ProgressRequestBody(id, MediaType.parse("application/octet-stream"), file, progressListener);

        //1.由MultipartBody构造RequestBody
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);

        builder.addFormDataPart("file", fileRequestBody.getFilename(), fileRequestBody);

        SortedMap<String, String> signParams = new TreeMap<String, String>();

        if (paramsMaps != null && paramsMaps.size() > 0) {

            String mValue;

            //遍历集合, map集合遍历方式
            for (String key : paramsMaps.keySet()) {
                mValue = paramsMaps.get(key);

                if (mValue != null) {
                    builder.addFormDataPart(key, paramsMaps.get(key));
                    signParams.put(key, mValue);
                }
            }
        }

        String time = TimeUtil.getCurrentTimeMillis();

        builder.addFormDataPart("time", time).addFormDataPart("sign", MD5Util.sha1AndMd5(StringUtils.createKeyValueSign(signParams) + Constants.KeySignSecret + time));

        OkHttpIO.getInstance().post(url, builder.build(), new Callback<Tuple2<Integer, String>, Exception>() {
            @Override
            public void onSuccess(Tuple2<Integer, String> res) {
                if (callback != null) {
                    callback.onComplete();

                    try {
                        if (res._1 == 200) {
                            JSONObject jsonObject = JSON.parseObject(res._2);

                            int code = jsonObject.getInteger("code");

                            if (code == 200) { //OK
                                callback.onSuccess(res._2);
                            } else {
                                callback.onError(new Tuple2(code, jsonObject.getString("message")));

                            }
                        } else {
                            callback.onError(new Tuple2(res._1, String.format("HTTP CODE : %d", res._1)));
                        }
                    } catch (Exception e) {
                        LogUtils.e("数据解析异常: " + e.getMessage());
                    }
                }
            }

            @Override
            public void onError(Exception error) {
                if (callback != null) {
                    LogUtils.e("数据请求异常: " + error.getMessage());
                    callback.onComplete();
                    callback.onError(new Tuple2(BaseApiIO.RESULT_REQUEST_EXCEPTION_CODE, BaseApiIO.RESULT_REQUEST_EXCEPTION));
                }
            }
        });
    }

    /**
     * 异步下载文件接口
     *
     * @param url              短地址
     * @param savePath         文件保存路径
     * @param saveName         文件保存名
     * @param downloadListener 回调
     */
    public void postDownLoad(@NonNull String url, @NonNull final String savePath, @NonNull final String saveName, @Nullable final OnDownloadListener downloadListener) {
        LogUtils.d("--->url: " + url);
        OkHttpIO.getInstance().postDownload(url, savePath, saveName, new OnDownloadListener() {
            @Override
            public void onDownloadSuccess() {
                if (downloadListener != null) {
                    downloadListener.onDownloadSuccess();
                }
            }

            @Override
            public void onDownloading(long total, long current) {
                if (downloadListener != null) {
                    downloadListener.onDownloading(total, current);
                }
            }

            @Override
            public void onDownloadFailed(Exception e) {
                if (downloadListener != null) {
                    downloadListener.onDownloadFailed(e);
                }
            }
        });
    }

    /**
     * 异步下载文件接口
     *
     * @param url              短地址
     * @param saveFile         保存的文件
     * @param downloadListener 回调
     */
    public void postDownLoad(@NonNull String url, @NonNull final File saveFile, @Nullable final OnDownloadListener downloadListener) {
        LogUtils.d("--->url: " + url);
        OkHttpIO.getInstance().postDownload(url, saveFile, new OnDownloadListener() {
            @Override
            public void onDownloadSuccess() {
                if (downloadListener != null) {
                    downloadListener.onDownloadSuccess();
                }
            }

            @Override
            public void onDownloading(long total, long current) {
                if (downloadListener != null) {
                    downloadListener.onDownloading(total, current);
                }
            }

            @Override
            public void onDownloadFailed(Exception e) {
                if (downloadListener != null) {
                    downloadListener.onDownloadFailed(e);
                }
            }
        });
    }

    /**
     * 发起 GET 请求
     *
     * @param url
     * @param callback
     */
    public void getBitmap(@NonNull String url, final APIRequestCallback<Bitmap, Tuple2<Integer, String>> callback) {

        OkHttpIO.getInstance().getBitmap(url, new BitmapCallback<Bitmap, String>() {
            @Override
            public void onSuccess(Bitmap res) {
                if (callback != null) {
                    callback.onSuccess(res);
                    callback.onComplete();
                }
            }

            @Override
            public void onError(String error) {
                if (callback != null) {
                    callback.onError(new Tuple2(-1, error));
                    callback.onComplete();
                }
            }
        });
    }
}
